<?php
/**
 * 模板标签解析器.
 *
 * 可以通过继承该抽象类,扩展模板的标签解析.在扩展模板的标签解析时实现'compile'方法即可.
 * 该方法接收一段match到的标签内容进行解析操作并返回解析后的结果.
 *
 * @author Qiong Wu <papa0924@gmail.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.windframework.com
 *
 * @version $Id: AbstractWindTemplateCompiler.php 3533 2012-05-08 08:24:20Z yishuo $
 */
abstract class AbstractWindTemplateCompiler extends WindHandlerInterceptor
{
    /**
     * @var array
     */
    protected $tags = array();
    /**
     * @var WindViewTemplate
     */
    protected $windViewTemplate = null;
    /**
     * @var WindViewerResolver
     */
    protected $windViewerResolver = null;
    /**
     * @var WindHttpRequest
     */
    protected $request = null;
    /**
     * @var WindHttpResponse
     */
    protected $response = null;
    /**
     * @var array
     */
    protected $_propertiesCache = array();

    /**
     * 初始化标签解析器.
     *
     * @param string             $tags
     * @param WindViewTemplate   $windViewTemplate
     * @param WindViewerResolver $windViewerResolver
     * @param WindHttpRequest    $request
     * @param WindHttpResponse   $response
     */
    public function __construct($tags, $windViewTemplate, $windViewerResolver, $request, $response)
    {
        $this->tags = $tags;
        $this->windViewTemplate = $windViewTemplate;
        $this->windViewerResolver = $windViewerResolver;
        $this->request = $request;
        $this->response = $response;
    }

    /**
     * 内容编译,接受一段落内容进行编译处理并返回编译内容.
     *
     * @param string $key
     * @param string $content 模板内容
     *
     * @return string 输出编译后结果
     */
    abstract public function compile($key, $content);

    /**
     * 编译前预处理.
     */
    protected function preCompile()
    {
    }

    /**
     * 编译后处理结果.
     */
    protected function postCompile()
    {
    }

    /**
     * 返回该标签支持的属性列表,需要覆盖该方法实现对标签的解析支持
     *
     * @return array
     */
    protected function getProperties()
    {
        return array();
    }

    /**
     * 解析标签属性值
     *
     * @param string $content
     */
    protected function compileProperty($content)
    {
        foreach ($this->getProperties() as $value) {
            if (!$value || !property_exists($this, $value)) {
                continue;
            }
            if (!isset($this->_propertiesCache[$value])) {
                $this->_propertiesCache[$value] = $this->$value;
            }
            preg_match('/(?<='.preg_quote($value).'=([\'\"]))(.*?)(?=\1)/ie', $content, $result);
            $this->$value = $result ? $result[0] : $this->_propertiesCache[$value];
        }
    }

    /* (non-PHPdoc)
     * @see WindHandlerInterceptor::preHandle()
     */
    public function preHandle()
    {
        if ($this->windViewTemplate === null) {
            return;
        }
        $this->preCompile();
        foreach ($this->tags as $key => $value) {
            if (!$value[0] || !$value[1]) {
                continue;
            }
            $this->compileProperty($value[1]);
            $_output = $this->compile($value[0], $value[1]);
            $this->windViewTemplate->setCompiledBlockData($value[0], $_output);
        }
        $this->postCompile();
    }

    /* (non-PHPdoc)
     * @see WindHandlerInterceptor::postHandle()
     */
    public function postHandle()
    {
    }

    /* (non-PHPdoc)
     * @see WindHandlerInterceptor::handle()
     */
    public function handle()
    {
        $args = func_get_args();
        call_user_func_array(array($this, 'preHandle'), $args);
        if (null !== ($handler = $this->interceptorChain->getHandler())) {
            call_user_func_array(array($handler, 'handle'), $args);
        }
        call_user_func_array(array($this, 'postHandle'), $args);
    }

    /**
     * @return WindViewTemplate
     */
    protected function getWindViewTemplate()
    {
        return $this->windViewTemplate;
    }
}
